/*************************************************
 * 
 * Copyright by Bruno Eberhard
 * 
 * Created on 29.07.2005
 *
 *************************************************/
package fightplan.views.tables;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;

import com.jgoodies.binding.value.ValueModel;

import fightplan.actions.UndoRedoManager;
import fightplan.actions.UndoRedoManagerProvider;
import fightplan.actions.UndoableAction;
import fightplan.bindx.GObservableList;
import fightplan.business.Category;
import fightplan.business.Dojo;
import fightplan.business.Team;
import fightplan.business.Tournament;
import fightplan.core.FPExceptionHandler;
import fightplan.core.Style;
import fightplan.ui.TwoLineStringSplitter;
import fightplan.views.MainView;

@SuppressWarnings("serial")
public class DojoTable extends JPanel implements UndoRedoManagerProvider {
	private JTable table;
	private DojoTableModel tableModel;
	private ValueModel tournamentModel;

	public DojoTable(ValueModel tournamentModel) {
		super(new BorderLayout());
		this.tournamentModel = tournamentModel;

		tableModel = new DojoTableModel();
		tournamentModel.addValueChangeListener(tableModel);

		table = new JTable(tableModel);
		table.setRowHeight(20);
		table.putClientProperty(fightplan.actions.SelectAllAction.MENU_CONTROLLED, Boolean.TRUE);

		TableRowSorter<DojoTableModel> sorter = new TableRowSorter<DojoTableModel>(tableModel);
		table.setRowSorter(sorter);

		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.getViewport().setBackground(Style.UNUSED_TABLE_SPACE);
		scrollPane.setPreferredSize(new Dimension(5000, 5000));

		add(scrollPane, BorderLayout.CENTER);
		add(createActions(), BorderLayout.SOUTH);
	}

	public UndoRedoManager getUndoRedoManager() {
		return ((MainView) SwingUtilities.getWindowAncestor(this)).getUndoRedoManager();
	}

	private JPanel createActions() {
		JPanel panel = new JPanel(new FlowLayout(SwingConstants.RIGHT));
		panel.add(createNewButton());
		return panel;
	}

	private Tournament getTournament() {
		return (Tournament) tournamentModel.getValue();
	}

	private JButton createNewButton() {

		Action addDojoAction = new UndoableAction("Dojo hinzufügen", this, "Dojo wieder entfernen") {

			public boolean doAction(ActionEvent e) {
				tableModel.addElement(new Dojo());
				return true;
			}
		};
		return new JButton(addDojoAction);
	}

	//

	// private class PriceCellRenderer extends DefaultTableCellRenderer {
	//
	// public Component getTableCellRendererComponent(JTable table, Object
	// value, boolean isSelected, boolean hasFocus, int row, int column) {
	// JLabel label = (JLabel)super.getTableCellRendererComponent(table, value,
	// isSelected, hasFocus, row, column);
	// label.setText("" + ((Dojo)value).getPrice(getTournament()));
	// return label;
	// }
	// }

	private class DojoTableModel extends AbstractTableModel implements PropertyChangeListener, ListDataListener {
		private GObservableList<Dojo> dojos;
		private GObservableList<Category> categories;

		public DojoTableModel() {
			dojos = getTournament() != null ? getTournament().getDojos() : null;
			categories = getTournament() != null ? getTournament().getCategories() : null;
			if (dojos != null) {
				dojos.addListDataListener(this);
			}
			if (categories != null) {
				categories.addListDataListener(this);
			}
		}

		public int getColumnCount() {
			return getTeamCategories().size() + 3;
		}

		public void addElement(Dojo dojo) {
			getTournament().getDojos().add(dojo);
			fireTableStructureChanged();
		}

		public void propertyChange(PropertyChangeEvent evt) {
			if (dojos != null) {
				dojos.removeListDataListener(this);
			}
			if (categories != null) {
				categories.removeListDataListener(this);
			}
			dojos = getTournament() != null ? getTournament().getDojos() : null;
			categories = getTournament() != null ? getTournament().getCategories() : null;
			if (dojos != null) {
				dojos.addListDataListener(this);
			}
			if (categories != null) {
				categories.addListDataListener(this);
			}

			fireTableStructureChanged();

			// Bewirkt eine korrekte Höhe des TableHeaders
			// Siehe BasicTableHeaderUI.getHeaderHeight()
			table.getColumnModel().getColumn(0).setHeaderRenderer(table.getTableHeader().getDefaultRenderer());
		}

		public void intervalAdded(ListDataEvent e) {
			fireTableStructureChanged();
		}

		public void intervalRemoved(ListDataEvent e) {
			fireTableStructureChanged();
		}

		public void contentsChanged(ListDataEvent e) {
			fireTableStructureChanged();
		}

		public int getRowCount() {
			return getTournament() != null ? getTournament().getDojos().size() : 0;
		}

		public Object getValueAt(int rowIndex, int columnIndex) {
			Dojo dojo = (Dojo) getTournament().getDojos().getElementAt(rowIndex);
			if (columnIndex == 0) {
				return dojo.getName();
			} else if (columnIndex == getColumnCount() - 2) {
				return dojo.getFighterCount(getTournament());
			} else if (columnIndex == getColumnCount() - 1) {
				return dojo.getPrice(getTournament());
			} else {
				return dojo.getTeamCount(getTeamCategories().get(columnIndex - 1));
			}
		}

		@Override
		public Class<?> getColumnClass(int columnIndex) {
			return columnIndex == 0 ? String.class : Integer.class;
		}

		@Override
		public String getColumnName(int column) {
			if (column == 0) {
				return "Dojo";
			} else if (column == getColumnCount() - 2) {
				return "Einzelanmeldungen";
			} else if (column == getColumnCount() - 1) {
				return "Gebühren";
			} else {
				return TwoLineStringSplitter.split(getTeamCategories().get(column - 1).getNameOrDescription());
			}
		}

		@Override
		public boolean isCellEditable(int rowIndex, int columnIndex) {
			return columnIndex < getColumnCount() - 2;
		}

		@Override
		public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
			Dojo dojo = (Dojo) getTournament().getDojos().getElementAt(rowIndex);
			if (columnIndex == 0) {
				dojo.setName("" + aValue);
			} else {
				Category category = getTeamCategories().get(columnIndex - 1);
				int newTeams = (Integer) aValue;
				int oldTeams = dojo.getTeamCount(getTeamCategories().get(columnIndex - 1));

				if (newTeams != oldTeams && category.isPlanned()) {
					FPExceptionHandler.instance().showInformation(
							"Kategorie bereits ausgelost.\nDie Anzahl Teams kann nicht mehr geändert werden.",
							"Keine Aenderung möglich");
					return;
				}

				if (oldTeams < newTeams) {
					for (int i = oldTeams; i < newTeams; i++) {
						Team team = new Team();
						team.setCategory(category);
						team.setDojo(dojo);
						if (i != 0 || newTeams > 1)
							team.setNumber(i + 1);
						category.addFighter(team);
					}
				} else if (oldTeams > newTeams) {
					for (int i = oldTeams - 1; i >= newTeams; i--) {
						for (int j = category.getFighters().size() - 1; j >= 0; j--) {
							Team team = (Team) category.getFighters().get(j);
							if (!dojo.equals(team.getDojo()))
								continue;
							category.getFighters().remove(j);
							break;
						}
					}
				}
			}
		}

		private List<Category> getTeamCategories() {
			List<Category> categories = new ArrayList<Category>();
			if (getTournament() != null) {
				for (Category category : getTournament().getCategories()) {
					if (!category.isTeam())
						continue;
					categories.add(category);
				}
			}
			return categories;
		}

	}

}